package com.bjx.common.data.scope.interceptor;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.toolkit.PluginUtils;
import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor;
import com.bjx.common.security.domain.UserPostVO;
import com.bjx.common.data.scope.ScopeHandler;
import com.bjx.common.data.scope.annotation.DataScope;
import com.bjx.common.security.domain.LoginUserVO;
import com.bjx.common.security.util.LoginUtil;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;
import java.util.stream.Collectors;



/**
 * @desc: 数据权限过滤器
 * @author: liushuai
 * @date: 2022/10/19 17:17
 */
public class DataScopeInnerInterceptor implements InnerInterceptor {

    /**
     *  当前用户
     */
    private static Byte CURRENT_USER = 1;

    private static Byte CURRENT_ORG = 2;

    private static Byte CURRENT_ORG_SON = 3;

    private static Byte CURRENT_COMPANY = 4;

    private static Byte CURRENT_COMPANY_SON = 5;


    @Override
    public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds,
                            ResultHandler resultHandler, BoundSql boundSql) {
        PluginUtils.MPBoundSql mpBs = PluginUtils.mpBoundSql(boundSql);
        String originalSql = boundSql.getSql();
        //采用判断方法注解方式进行数据权限
        Class<?> clazz = null;
        try {
            //获取Mapper类
            clazz = Class.forName(ms.getId().substring(0, ms.getId().lastIndexOf(".")));
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        // 获取方法名
        String methodName = ms.getId().substring(ms.getId().lastIndexOf(".") + 1);
        //注解作用到类
        DataScope dataScope = clazz.getAnnotation(DataScope.class);
        Method[] methods = clazz.getMethods();
        //遍历类的方法
        for (Method method : methods) {
            DataScope scope = method.getAnnotation(DataScope.class);
            //判断是否存在注解且方法名一致
            if (scope != null && methodName.equals(method.getName())) {
                dataScope = scope;
            }
        }
        if(ObjectUtil.isNotEmpty(dataScope)){
            originalSql = setCurrentSqlScope(originalSql,dataScope);
        }
        mpBs.sql(originalSql);
    }

    /**
     * 设置当前用户的数据权限范围
     * @param originalSql
     * @return: java.lang.String
     * @Author: liushuai
     * @Date: 2022/10/22 11:44
     */
    public String setCurrentSqlScope(String originalSql,DataScope dataScope){
        LoginUserVO loginUserVO = LoginUtil.loginInfo();
        List<UserPostVO> currentUserPosts = loginUserVO.getPosts();
        String[] posts = dataScope.posts();
        if(posts.length > 0 && CollectionUtil.isNotEmpty(currentUserPosts)){
            List<String> postList = Arrays.asList(posts);
            //过滤不需要得用户职位
            currentUserPosts = currentUserPosts.stream().filter(res -> !postList.contains(res.getPostCode())).collect(Collectors.toList());
        }
        //组装数据结构
        Map<Byte,List<Long>> scopeMap = new HashMap<Byte,List<Long>>();
        if(CollectionUtil.isNotEmpty(currentUserPosts)){
            for(UserPostVO vo : currentUserPosts) {
                List<Long> ids = scopeMap.get(vo.getDataCode());
                if(CollectionUtil.isNotEmpty(ids)){
                    if(vo.getDataCode() == CURRENT_COMPANY.byteValue() || vo.getDataCode() == CURRENT_COMPANY_SON.byteValue()){
                        ids.add(Long.valueOf(vo.getComId()));
                    }else{
                        ids.add(Long.valueOf(vo.getOrgId()));
                    }

                }else{
                    ids = new ArrayList<Long>();
                    if(vo.getDataCode() == CURRENT_COMPANY.byteValue() || vo.getDataCode() == CURRENT_COMPANY_SON.byteValue()){
                        ids.add(Long.valueOf(vo.getComId()));
                    }else{
                        ids.add(Long.valueOf(vo.getOrgId()));
                    }
                }
                scopeMap.put(vo.getDataCode(),ids);
            }
        }
        //执行拼接
        if(CollectionUtil.isNotEmpty(scopeMap)){
            String sql = "";
            ScopeHandler scopeHandler = new ScopeHandler();
            for (Map.Entry<Byte,List<Long>> entry:scopeMap.entrySet()){
                try {
                    Method method = scopeHandler.getClass().getMethod("sql_" + entry.getKey(), LoginUserVO.class, List.class, DataScope.class);
                    sql += (String) method.invoke(scopeHandler,loginUserVO,entry.getValue(),dataScope);
                } catch (NoSuchMethodException e) {
                    throw new RuntimeException(e);
                } catch (InvocationTargetException e) {
                    throw new RuntimeException(e);
                } catch (IllegalAccessException e) {
                    throw new RuntimeException(e);
                }
            }
            sql = sql.replace("OR","");
            //合并sql
            originalSql = ScopeHandler.SqlMerge(originalSql,sql);
        }

        return originalSql;
    }


}
